package com.xyxeshang.es.music.backend.service.impl;

import com.xyxeshang.es.music.backend.constant.ResultConstant;
import com.xyxeshang.es.music.backend.entity.*;
import com.xyxeshang.es.music.backend.exception.CustomException;
import com.xyxeshang.es.music.backend.mapper.*;
import com.xyxeshang.es.music.backend.service.SongService;
import com.xyxeshang.es.music.backend.util.EsRedisUtil;
import com.xyxeshang.es.music.backend.util.ResultUtil;
import com.xyxeshang.es.music.backend.util.EsMusicUtil;
import org.apache.ibatis.jdbc.Null;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

/**
 * @author xyx-Eshang
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class SongServiceImpl implements SongService {

	@Resource
	private SongMapper songMapper;

	@Resource
	private AlbumMapper albumMapper;

	@Resource
	private ArtistMapper artistMapper;

	@Resource
	private SongArtistMapper songArtistMapper;

	@Resource
	private SongCommentMapper songCommentMapper;

	@Resource
	private SongLikeMapper songLikeMapper;

	@Resource
	private ListenMapper listenMapper;

	/**
	 * 底层函数：判断是否为热门歌曲
	 *
	 * @param songName
	 * @return
	 * @throws IOException
	 */
	private Boolean baseCheckHotOrNot(String songName) {
		List<Song> songList = EsRedisUtil.getHotSearch(songName);
		return songList.size() != 0;
	}

	/**
	 * 底层函数：将song对象完整封装
	 *
	 * @param song
	 * @return
	 */
	private Song basePackage(Song song) {
		String songId = song.getSongId();
		Integer songLikeCount = songLikeMapper.getCountBySongId(songId);
		List<SongComment> songCommentList = songCommentMapper.listBySongId(songId);
		Integer songCommentCount = songCommentList.size();
		song.setSongLikeCount(songLikeCount)
				.setSongCommentList(songCommentList)
				.setSongCommentCount(songCommentCount);
		return song;
	}

	/**
	 * 搜索歌曲
	 *
	 * @param key
	 * @param offset
	 * @return
	 */
	@Override
	public ResultUtil<List<Song>> searchSong(String key, Integer offset) {
		try {
			//1. 如果是热门搜索词，从redis中获取
			List<Song> songList = EsRedisUtil.getHotSearch(key);

			//2. 不是热门搜索词
			if (songList.size() == 0) {
				//发送请求获取
				songList = EsMusicUtil.listByKey(key, offset);
				//遍历这些数据，存储入数据库
				for (Song song : songList) {
					String songId = song.getSongId();
					//2-1. 歌曲song
					if (songMapper.getById(songId) == null) {
						songMapper.save(song);
					}
					//2-2. 专辑album
					String albumId = song.getAlbumId();
					if (albumMapper.getById(albumId) == null) {
						albumMapper.save(song.getAlbum());
					}
					//2-3. 作者artist：
					for (Artist artist : song.getArtistList()) {
						String artistId = artist.getArtistId();
						if (artistMapper.getById(artistId) == null) {
							artistMapper.save(artist);
						}
					}
					//2-4. songArtist：先判断原来数据库中是否有数据
					List<SongArtist> songArtistList = songArtistMapper.listBySongId(songId);
					//2-4-1. 有数据时，判断这首歌的作者是否变更
					if (songArtistList.size() != 0) {
						Set<String> oldArtistIdSet = new HashSet<>();

						for (SongArtist songArtist : songArtistList) {
							String artistId = songArtist.getArtistId();
							oldArtistIdSet.add(artistId);
						}
						for (Artist artist : song.getArtistList()) {
							String artistId = artist.getArtistId();
							oldArtistIdSet.add(artistId);
						}
						// 如果作者变更，删除原数据，重新新增
						if (oldArtistIdSet.size() != song.getArtistList().size()) {
							songArtistMapper.deleteBySongId(songId);
							for (Artist artist : song.getArtistList()) {
								SongArtist songArtist = new SongArtist()
										.setSongId(songId)
										.setArtistId(artist.getArtistId());
								songArtistMapper.save(songArtist);
							}
						}
					}
					//2-4-2. 无数据时，直接新增即可
					else {
						for (Artist artist : song.getArtistList()) {
							SongArtist songArtist = new SongArtist()
									.setSongId(songId)
									.setArtistId(artist.getArtistId());
							songArtistMapper.save(songArtist);
						}
					}
				}
			}
			return new ResultUtil<>("songList", songList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 根据歌曲id和类型获取歌曲信息
	 *
	 * @param songId
	 * @param type
	 * @return
	 */
	@Override
	public ResultUtil<Song> getSong(String songId, String type) {
		try {
			List<Song> songList;
			if ("hot".contentEquals(type)) {
				songList = EsRedisUtil.getHotBillboard(-1);
			} else if ("new".contentEquals(type)) {
				songList = EsRedisUtil.getNewBillboard(-1);
			} else if ("up".contentEquals(type)) {
				songList = EsRedisUtil.getUpBillboard(-1);
			} else if ("tikTok".contentEquals(type)) {
				songList = EsRedisUtil.getTikTokBillboard(-1);
			} else if ("normal".contentEquals(type)) {
				Song song = songMapper.getById(songId);
				return new ResultUtil<>("song", song);
			}
			// 其他情况，type不规范或没有传递type值
			else {
				Song song;
				songList = EsRedisUtil.getHotBillboard(-1);
				for (Song target : songList) {
					if (songId.contentEquals(target.getSongId())) {
						song = basePackage(target);
						return new ResultUtil<>("song", song);
					}
				}
				songList = EsRedisUtil.getNewBillboard(-1);
				for (Song target : songList) {
					if (songId.contentEquals(target.getSongId())) {
						song = basePackage(target);
						return new ResultUtil<>("song", song);
					}
				}
				songList = EsRedisUtil.getUpBillboard(-1);
				for (Song target : songList) {
					if (songId.contentEquals(target.getSongId())) {
						song = basePackage(target);
						return new ResultUtil<>("song", song);
					}
				}
				songList = EsRedisUtil.getTikTokBillboard(-1);
				for (Song target : songList) {
					if (songId.contentEquals(target.getSongId())) {
						song = basePackage(target);
						return new ResultUtil<>("song", song);
					}
				}
				//若没有return，说明歌曲不在榜单中
				song = songMapper.getById(songId);
				return new ResultUtil<>("song", song);
			}
			// 执行到这里，说明type规范
			Song song;
			for (Song target : songList) {
				if (songId.contentEquals(target.getSongId())) {
					song = basePackage(target);
					return new ResultUtil<>("song", song);
				}
			}
			//若没有return，说明歌曲不在榜单中
			song = songMapper.getById(songId);
			return new ResultUtil<>("song", song);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 播放歌曲
	 *
	 * @param request
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<String> playSong(HttpServletRequest request, String songId) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			//1. 获取音乐源
			String songUrl = EsMusicUtil.getSongUrl(songId);
			if (!"暂无音乐源".contentEquals(songUrl)) {
				//2. 操作听歌记录
				Listen listen1 = new Listen()
						.setListenTime(new Date())
						.setListenCount(1)
						.setUserOpenId(userOpenId)
						.setSongId(songId);
				Listen listen2 = listenMapper.getByUserOpenIdAndSongId(listen1);

				// 如果不是首次听歌
				if (listen2 != null) {
					Integer listenCount = listen2.getListenCount() + 1;
					listenMapper.deleteById(listen2.getListenId());
					listen1.setListenCount(listenCount);
				}
				listenMapper.save(listen1);
			}
			return new ResultUtil<>("songUrl", songUrl);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 获取榜单歌曲
	 *
	 * @param type
	 * @return
	 * @Param count
	 */
	@Override
	public ResultUtil<List<Song>> getBillboard(String type, Integer count) {
		try {
			List<Song> songList;
			//1. 从redis中获取数据
			// 热歌榜
			if ("hot".contentEquals(type)) {
				songList = EsRedisUtil.getHotBillboard(count);
			}
			// 新歌榜
			else if ("new".contentEquals(type)) {
				songList = EsRedisUtil.getNewBillboard(count);
			}
			// 飙升榜
			else if ("up".contentEquals(type)) {
				songList = EsRedisUtil.getUpBillboard(count);
			}
			// 抖音排行榜
			else if ("tikTok".contentEquals(type)) {
				songList = EsRedisUtil.getTikTokBillboard(count);
			}
			// 参数错误
			else {
				throw new CustomException(ResultConstant.PARAMETER_IS_WRONG);
			}

			// 如果redis中没有，直接请求
			if (songList.size() == 0) {
				songList = EsMusicUtil.listFromBillboard(type);
			}
			return new ResultUtil<>("songList", songList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 新增评论
	 *
	 * @param request
	 * @param songCommentContent
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<Integer> addComment(HttpServletRequest request, String songCommentContent, String songId) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			SongComment songComment = new SongComment()
					.setSongCommentContent(songCommentContent)
					.setSongCommentTime(new Date())
					.setSongId(songId)
					.setUserOpenId(userOpenId);
			songCommentMapper.save(songComment);
			return new ResultUtil<>("songCommentId", songComment.getSongCommentId());
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 删除评论
	 *
	 * @param songCommentId
	 * @return
	 */
	@Override
	public ResultUtil<Null> deleteComment(Integer songCommentId) {
		try {
			songCommentMapper.deleteById(songCommentId);
			return new ResultUtil<>();
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 根据歌曲id，查询我的评论
	 *
	 * @param request
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<List<SongComment>> listMyComment(HttpServletRequest request, String songId) {
		try {
			List<SongComment> songCommentList = songCommentMapper.listBySongId(songId);
			return new ResultUtil<>("songCommentList", songCommentList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 根据歌曲id查询所有评论
	 *
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<List<SongComment>> listComment(String songId) {
		try {
			List<SongComment> songCommentList = songCommentMapper.listBySongId(songId);
			return new ResultUtil<>("songCommentList", songCommentList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 新增点赞
	 *
	 * @param request
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<Integer> addLike(HttpServletRequest request, String songId) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			SongLike songLike = new SongLike()
					.setSongLikeTime(new Date())
					.setSongId(songId)
					.setUserOpenId(userOpenId);
			songLikeMapper.save(songLike);
			return new ResultUtil<>("songLikeId", songLike.getSongLikeId());
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 取消点赞
	 *
	 * @param songLikeId
	 * @return
	 */
	@Override
	public ResultUtil<Null> deleteLike(Integer songLikeId) {
		try {
			songLikeMapper.deleteById(songLikeId);
			return new ResultUtil<>();
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 根据歌曲id，查询我的点赞记录
	 *
	 * @param request
	 * @param songId
	 * @return
	 */
	@Override
	public ResultUtil<SongLike> getMySongLike(HttpServletRequest request, String songId) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			SongLike songLike = new SongLike()
					.setUserOpenId(userOpenId)
					.setSongId(songId);
			songLike = songLikeMapper.getByUserOpenIdAndSongId(songLike);
			return new ResultUtil<>("songLike", songLike);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 查询我点赞的歌曲
	 *
	 * @param request
	 * @return
	 */
	@Override
	public ResultUtil<List<Song>> listMyLikeSong(HttpServletRequest request) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			List<Song> songList = songMapper.listLikeSongByUserOpenId(userOpenId);
			return new ResultUtil<>("songList", songList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}

	/**
	 * 查询我的听歌记录
	 *
	 * @param request
	 * @return
	 */
	@Override
	public ResultUtil<List<Listen>> listMyListen(HttpServletRequest request) {
		try {
			String userOpenId = (String) request.getAttribute("userOpenId");
			List<Listen> listenList = listenMapper.listByUserOpenId(userOpenId);
			return new ResultUtil<>("listenList", listenList);
		} catch (Exception e) {
			return new ResultUtil<>(e);
		}
	}


}
